package com.meta.nd.service.filter.utils;

import com.meta.cache.NdCacheService;
import com.meta.nd.filter.bo.FilterParamDef;
import com.meta.nd.filter.vo.FilterFd;
import com.meta.nd.filter.vo.ResultFd;
import com.meta.nd.service.filter.bo.TableTree;
import com.meta.nd.util.NdDbMapping;
import com.meta.nd.util.SpringBeanUtil;
import com.meta.nd.vo.Nd;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class TableTreeBuilder {

public static TableTree build(Nd nd, FilterParamDef filterDef){
    String returnNdCode = filterDef.getReturnNdCode();
    TableTree tableTree = reverseTableTree(nd,returnNdCode);
    clipTree(tableTree,getAllRelatedNdCodes(nd,filterDef));
    setFilterInfo(tableTree,filterDef);
    return tableTree;
}

private static TableTree reverseTableTree( Nd nd, String returnNdCode){
    TableTree entireTree = buildEntireTree(nd);
    TableTree currentNode = entireTree.getTreeNodeByNdCode(returnNdCode);
    TableTree returnTree = currentNode;
    TableTree parent = currentNode.getParent();
    while( parent!= null){
        parent.setReverse(true);
        TableTree temp = parent.getParent();
        parent.setParent(currentNode);
        parent.getChildren().remove(currentNode);
        currentNode.addChild(parent);
        currentNode = parent;
        parent = temp;
    }
    return returnTree;
}


public static TableTree buildEntireTree(Nd nd) {
    TableTree tableTree = new TableTree();
    tableTree.setNd(nd);
    NdDbMapping dbMapping = SpringBeanUtil.getNdCacheService().getNdDbMapping(nd.getDbMapCode());
    tableTree.setDbMapping(dbMapping);
    for (Nd child : nd.getChildren()) {
        tableTree.addChild(buildEntireTree(child));
    }
    return tableTree;
}


private static List<String> getAllRelatedNdCodes( Nd nd, FilterParamDef filterDef){
    List<String> relatedNdCodes = new ArrayList<>();
    String returnNdCode = filterDef.getReturnNdCode();
    Nd returnNd = nd.findNdByNdCode(returnNdCode);
    if ( returnNd == null)
         throw new RuntimeException(String.format("查询定义返回ndCode:%s不存在！查询定义代码为：%s", returnNdCode,filterDef.getFilterDefCode()));
    relatedNdCodes.add(returnNd.getNdCode());
    for(FilterFd filterFd : filterDef.getFilterFds()){
        String ndName = filterFd.getNdName();
        Nd relatedNd = nd.findNdByNdName(ndName);
        if ( relatedNd == null )
            throw new RuntimeException(String.format("查询定义查询ndName：%s不存在！查询定义代码为：%s", ndName,filterDef.getFilterDefCode()));
        if (!relatedNdCodes.contains(relatedNd.getNdCode()))
            relatedNdCodes.add(relatedNd.getNdCode());
    }
    for(ResultFd resultFd : filterDef.getResultFds()){
        String ndName = resultFd.getNdName();
        Nd relatedNd = nd.findNdByNdName(ndName);
        if ( relatedNd == null )
            throw new RuntimeException(String.format("查询定义结果ndName：%s不存在！查询定义代码为：%s", ndName,filterDef.getFilterDefCode()));
        if (!relatedNdCodes.contains(relatedNd.getNdCode()))
            relatedNdCodes.add(relatedNd.getNdCode());
    }
    return relatedNdCodes;
}
private static void clipTree( TableTree tableTree, List<String> relatedNdCodes){
    for( int i=tableTree.getChildren().size()-1; i>=0; i-- ){
        TableTree child = tableTree.getChildren().get(i);
        clipTree(child,relatedNdCodes);
    }
    String ndCode = tableTree.getNd().getNdCode();
    if( !relatedNdCodes.contains(ndCode) && tableTree.getChildren().size() == 0)
        tableTree.getParent().getChildren().remove(tableTree);
}

private static void setFilterInfo(TableTree tableTree,  FilterParamDef filterDef){
    String ndName = tableTree.getNd().getNdName();
    NdCacheService ndCacheService = SpringBeanUtil.getNdCacheService();
    String dbMapCode = tableTree.getNd().getDbMapCode();
    if (!StringUtils.isEmpty(dbMapCode)) {
        NdDbMapping ndDbMapping= ndCacheService.getNdDbMapping(dbMapCode);
        tableTree.setNvTableName(ndDbMapping.getNvTableName());
        tableTree.setFvTableName(ndDbMapping.getFvTableName());
    }
    for( FilterFd filterFd : filterDef.getFilterFds()){
        if ( filterFd.getNdName().equals(ndName))
            tableTree.getFilterFds().add(filterFd);
    }
    for( ResultFd resultFd : filterDef.getResultFds()){
        if ( resultFd.getNdName().equals(ndName))
            tableTree.getResultFds().add(resultFd);
    }
    for( TableTree child : tableTree.getChildren())
        setFilterInfo(child,filterDef);
}
}
